home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / ARRAY.C < prev    next >
C/C++ Source or Header  |  1991-12-20  |  64KB  |  2,263 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/users/cph/src/microcode/RCS/array.c,v 9.44 1991/12/20 22:48:36 cph Exp $
  4.  
  5. Copyright (c) 1987-91 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. #include "scheme.h"
  36. #include "prims.h"
  37. #include "array.h"
  38. #include <math.h>
  39. #include <values.h>
  40. /* <values.h> contains some math constants */
  41.  
  42. /* ARRAY (as a scheme object)
  43.    is a usual array (in C) containing REAL numbers (float/double)
  44.    and tagged as a non-marked vector.
  45.  
  46.    Basic contents:
  47.    constructors, selectors, arithmetic operations,
  48.    conversion routines between C_Array, and Scheme_Vector
  49.  
  50.    see array.h for macros, NM_VECTOR, and extern */
  51.  
  52. /* mathematical constants */
  53. #ifdef PI
  54. #undef PI
  55. #endif
  56. #define PI           3.141592653589793238462643
  57. #define PI_OVER_2    1.570796326794896619231322
  58. #define TWOPI        6.283185307179586476925287
  59. #define SQRT_2          1.4142135623730950488
  60. #define ONE_OVER_SQRT_2  .7071067811865475244
  61. /* Abramowitz and Stegun p.3 */
  62.  
  63. REAL
  64. flonum_to_real (argument, arg_number)
  65.      fast SCHEME_OBJECT argument;
  66.      int arg_number;
  67. {
  68.   switch (OBJECT_TYPE (argument))
  69.     {
  70.     case TC_FIXNUM:
  71.       return ((REAL) (FIXNUM_TO_DOUBLE (argument)));
  72.  
  73.     case TC_BIG_FIXNUM:
  74.       if (! (BIGNUM_TO_DOUBLE_P (argument)))
  75.       error_bad_range_arg (arg_number);
  76.       return ((REAL) (bignum_to_double (argument)));
  77.  
  78.     case TC_BIG_FLONUM:
  79.       return ((REAL) (FLONUM_TO_DOUBLE (argument)));
  80.  
  81.     default:
  82.       error_wrong_type_arg (arg_number);
  83.       /* NOTREACHED */
  84.     }
  85. }
  86.  
  87. SCHEME_OBJECT
  88. allocate_array (length)
  89.      long length;
  90. {
  91. #if (REAL_IS_DEFINED_DOUBLE == 0)
  92.  
  93.   fast SCHEME_OBJECT result =
  94.     (allocate_non_marked_vector
  95.      (TC_NON_MARKED_VECTOR, ((length * REAL_SIZE) + 1), true));
  96.   FAST_MEMORY_SET (result, 1, length);
  97.   return (result);
  98.  
  99. #else /* (REAL_IS_DEFINED_DOUBLE != 0) */
  100.   
  101.   long n_words = (length * DOUBLE_SIZE);
  102.   ALIGN_FLOAT (Free);
  103.   Primitive_GC_If_Needed (n_words + 1);
  104.   {
  105.     SCHEME_OBJECT result = (MAKE_POINTER_OBJECT (TC_BIG_FLONUM, (Free)));
  106.     (*Free++) = (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR, n_words));
  107.     Free += n_words;
  108.     return (result);
  109.   }
  110.  
  111. #endif /* (REAL_IS_DEFINED_DOUBLE != 0) */
  112. }
  113.  
  114. DEFINE_PRIMITIVE ("VECTOR->ARRAY", Prim_vector_to_array, 1, 1, 0)
  115. {
  116.   PRIMITIVE_HEADER (1);
  117.   CHECK_ARG (1, VECTOR_P);
  118.   {
  119.     SCHEME_OBJECT vector = (ARG_REF (1));
  120.     long length = (VECTOR_LENGTH (vector));
  121.     SCHEME_OBJECT result = (allocate_array (length));
  122.     fast SCHEME_OBJECT * scan_source = (& (VECTOR_REF (vector, 0)));
  123.     fast SCHEME_OBJECT * end_source = (scan_source + length);
  124.     fast REAL * scan_target = (ARRAY_CONTENTS (result));
  125.     while (scan_source < end_source)
  126.       (*scan_target++) = (flonum_to_real ((*scan_source++), 1));
  127.     PRIMITIVE_RETURN (result);
  128.   }
  129. }
  130.  
  131. DEFINE_PRIMITIVE ("ARRAY->VECTOR", Prim_array_to_vector, 1, 1, 0)
  132. {
  133.   PRIMITIVE_HEADER (1);
  134.   CHECK_ARG (1, ARRAY_P);
  135.   {
  136.     SCHEME_OBJECT array = (ARG_REF (1));
  137.     long length = (ARRAY_LENGTH (array));
  138.     fast REAL * scan_source = (ARRAY_CONTENTS (array));
  139.     fast REAL * end_source = (scan_source + length);
  140.     SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, length, true));
  141.     fast SCHEME_OBJECT * scan_result = (MEMORY_LOC (result, 1));
  142.     while (scan_source < end_source)
  143.       (*scan_result++) = (double_to_flonum ((double) (*scan_source++)));
  144.     PRIMITIVE_RETURN (result);
  145.   }
  146. }
  147.  
  148. DEFINE_PRIMITIVE ("ARRAY-ALLOCATE", Prim_array_allocate, 1,1, 0)
  149. {
  150.   fast REAL * scan;
  151.   long length;
  152.   SCHEME_OBJECT result;
  153.   PRIMITIVE_HEADER (1);
  154.  
  155.   length = (arg_nonnegative_integer (1));
  156.   result = (allocate_array (length));
  157.   for (scan = (ARRAY_CONTENTS (result)); --length >= 0; )
  158.     *scan++ = ((REAL) 0.0);
  159.   PRIMITIVE_RETURN (result);
  160. }
  161.  
  162. DEFINE_PRIMITIVE ("ARRAY-CONS-REALS", Prim_array_cons_reals, 3, 3, 0)
  163. {
  164.   PRIMITIVE_HEADER (3);
  165.   {
  166.     fast double from = (arg_real_number (1));
  167.     fast double dt = (arg_real_number (2));
  168.     long length = (arg_nonnegative_integer (3));
  169.     SCHEME_OBJECT result = (allocate_array (length));
  170.     fast REAL * scan_result = (ARRAY_CONTENTS (result));
  171.     fast int i;
  172.     for (i = 0; (i < length); i += 1)
  173.       {
  174.     (*scan_result++) = ((REAL) from);
  175.     from += dt;
  176.       }
  177.     PRIMITIVE_RETURN (result);
  178.   }
  179. }
  180.  
  181. DEFINE_PRIMITIVE ("ARRAY-LENGTH", Prim_array_length, 1, 1, 0)
  182. {
  183.   PRIMITIVE_HEADER (1);
  184.   CHECK_ARG (1, ARRAY_P);
  185.   PRIMITIVE_RETURN (LONG_TO_UNSIGNED_FIXNUM (ARRAY_LENGTH (ARG_REF (1))));
  186. }
  187.  
  188. DEFINE_PRIMITIVE ("ARRAY-REF", Prim_array_ref, 2, 2, 0)
  189. {
  190.   SCHEME_OBJECT array;
  191.   PRIMITIVE_HEADER (2);
  192.   CHECK_ARG (1, ARRAY_P);
  193.   array = (ARG_REF (1));
  194.   PRIMITIVE_RETURN
  195.     (double_to_flonum
  196.      ((double)
  197.       ((ARRAY_CONTENTS (array))
  198.        [arg_index_integer (2, (ARRAY_LENGTH (array)))])));
  199. }
  200.  
  201. DEFINE_PRIMITIVE ("ARRAY-SET!", Prim_array_set, 3, 3, 0)
  202. {
  203.   SCHEME_OBJECT array;
  204.   REAL * array_ptr;
  205.   double old_value, new_value;
  206.   PRIMITIVE_HEADER (3);
  207.   CHECK_ARG (1, ARRAY_P);
  208.   array = (ARG_REF (1));
  209.   array_ptr =
  210.     (& ((ARRAY_CONTENTS (array))
  211.     [arg_index_integer (2, (ARRAY_LENGTH (array)))]));
  212.   old_value = (*array_ptr);
  213.   new_value = (arg_real_number (3));
  214. #if (REAL_IS_DEFINED_DOUBLE == 0)
  215.   if ((new_value >= 0.0)
  216.       ? (new_value < ((double) FLT_MIN))
  217.       : (new_value > (0.0 - ((double) FLT_MIN))))
  218.     new_value = ((REAL) 0.0);
  219. #endif
  220.   (*array_ptr) = ((REAL) new_value);
  221.   PRIMITIVE_RETURN (double_to_flonum (old_value));
  222. }
  223.  
  224. /*____________________ file readers ___________
  225.   ascii and 2bint formats 
  226.   ______________________________________________*/
  227.  
  228. /* Reading data from files 
  229.    To read REAL numbers, use "lf" for double, "%f" for float 
  230.    */
  231. #if (REAL_IS_DEFINED_DOUBLE == 1)
  232. #define REALREAD  "%lf"
  233. #define REALREAD2 "%lf %lf"
  234. #else
  235. #define REALREAD  "%f"
  236. #define REALREAD2 "%f %f"
  237. #endif
  238.  
  239. static void
  240. C_Array_Read_Ascii_File (a, N, fp)          /* 16 ascii decimal digits */
  241.      REAL * a;
  242.      long N;
  243.      FILE * fp;
  244.   fast long i;
  245.   for (i = 0; (i < N); i += 1)
  246.     {
  247.       if ((fscanf (fp, REALREAD, (&(a[i])))) != 1)
  248.     { printf("Not enough values read ---\n last value a[%d] = % .16e \n", (i-1), a[i-1]);
  249.       error_external_return (); }
  250.     }
  251.   return;
  252. }
  253.  
  254. /* 2BINT FORMAT = integer stored in 2 consecutive bytes.
  255.    On many machines, "putw" and "getw" use 4 byte integers (C int)
  256.    so use "putc" "getc" as shown below.
  257.    */
  258.  
  259. static void
  260. C_Array_Read_2bint_File (a, N, fp)
  261.      REAL * a;
  262.      long N;
  263.      FILE * fp;
  264. {
  265.   fast long i;
  266.   fast int msd;
  267.   for (i = 0; (i < N); i += 1)
  268.     {
  269.       if (feof (fp))
  270.     error_external_return ();
  271.       msd = (getc (fp));
  272.       (a [i]) = ((REAL) ((msd << 8) | (getc (fp))));
  273.     }
  274.   return;
  275. }
  276.  
  277. DEFINE_PRIMITIVE ("ARRAY-READ-FROM-FILE", Prim_array_read_from_file, 3,3, 0)
  278. {
  279.   PRIMITIVE_HEADER (3);
  280.   CHECK_ARG (1, STRING_P);    /* 1 = filename */
  281.   /*                               2 = length of data */
  282.   CHECK_ARG (3, FIXNUM_P);    /* 3 = format of data   0=ascii 1=2bint  */
  283.   {
  284.     fast long length = (arg_nonnegative_integer (2));
  285.     fast SCHEME_OBJECT result = (allocate_array (length));
  286.     int format;
  287.     fast FILE * fp;
  288.     if ( (fp = fopen((STRING_ARG (1)), "r")) == NULL)
  289.       error_bad_range_arg (1);
  290.     
  291.     format = arg_nonnegative_integer(3);
  292.     if (format==0)
  293.       C_Array_Read_Ascii_File ((ARRAY_CONTENTS (result)), length, fp);
  294.     else if (format==1)
  295.       C_Array_Read_2bint_File ((ARRAY_CONTENTS (result)), length, fp);
  296.     else
  297.       error_bad_range_arg(3);    /* illegal format code */
  298.     
  299.     if ((fclose (fp)) != 0)
  300.       error_external_return ();
  301.     PRIMITIVE_RETURN (result);
  302.   }
  303. }
  304.  
  305. static void
  306. C_Array_Write_Ascii_File (a, N, fp)           /* 16 ascii decimal digits */
  307.      REAL * a;
  308.      long N;
  309.      FILE * fp;
  310. {
  311.   fast long i;
  312.   for (i = 0; (i < N); i += 1)
  313.     {
  314.       if (feof (fp))
  315.     error_external_return ();
  316.       fprintf (fp, "% .16e \n", a[i]);
  317.     }
  318.   return;
  319. }
  320.  
  321. DEFINE_PRIMITIVE ("ARRAY-WRITE-ASCII-FILE", Prim_array_write_ascii_file, 2, 2, 0)
  322. {
  323.   PRIMITIVE_HEADER (2);
  324.   CHECK_ARG (1, ARRAY_P);
  325.   CHECK_ARG (2, STRING_P);
  326.   {
  327.     fast SCHEME_OBJECT array = (ARG_REF (1));
  328.     fast FILE * fp = (fopen((STRING_ARG (2)), "w"));
  329.     if (fp == ((FILE *) 0))
  330.       error_bad_range_arg (2);
  331.     C_Array_Write_Ascii_File
  332.       ((ARRAY_CONTENTS (array)),
  333.        (ARRAY_LENGTH (array)),
  334.        fp);
  335.     if ((fclose (fp)) != 0)
  336.       error_external_return ();
  337.   }
  338.   PRIMITIVE_RETURN (UNSPECIFIC);
  339. }
  340.  
  341.  
  342.  
  343.  
  344. DEFINE_PRIMITIVE ("SUBARRAY-COPY!", Prim_subarray_copy, 5, 5, 0)
  345. {
  346.   PRIMITIVE_HEADER (5);
  347.   CHECK_ARG (1, ARRAY_P);    /* source array */
  348.   CHECK_ARG (2, ARRAY_P);    /* destination array */
  349.   {
  350.     REAL * source = (ARRAY_CONTENTS (ARG_REF (1)));
  351.     REAL * target = (ARRAY_CONTENTS (ARG_REF (2)));
  352.     long start_source = (arg_nonnegative_integer (3));
  353.     long start_target = (arg_nonnegative_integer (4));
  354.     long n_elements = (arg_nonnegative_integer (5));
  355.     if ((start_source + n_elements) > (ARRAY_LENGTH (ARG_REF (1))))
  356.       error_bad_range_arg (3);
  357.     if ((start_target + n_elements) > (ARRAY_LENGTH (ARG_REF (2))))
  358.       error_bad_range_arg (4);
  359.     {
  360.       fast REAL * scan_source = (source + start_source);
  361.       fast REAL * end_source = (scan_source + n_elements);
  362.       fast REAL * scan_target = (target + start_target);
  363.       while (scan_source < end_source)
  364.     (*scan_target++) = (*scan_source++);
  365.     }
  366.   }
  367.   PRIMITIVE_RETURN (UNSPECIFIC);
  368. }
  369.  
  370. DEFINE_PRIMITIVE ("ARRAY-REVERSE!", Prim_array_reverse, 1, 1, 0)
  371. {
  372.   PRIMITIVE_HEADER (1);
  373.   CHECK_ARG (1, ARRAY_P);
  374.   {
  375.     SCHEME_OBJECT array = (ARG_REF (1));
  376.     long length = (ARRAY_LENGTH (array));
  377.     long half_length = (length / 2);
  378.     fast REAL * array_ptr = (ARRAY_CONTENTS (array));
  379.     fast long i;
  380.     fast long j;
  381.     for (i = 0, j = (length - 1); (i < half_length); i += 1, j -= 1)
  382.       {
  383.     fast REAL Temp = (array_ptr [j]);
  384.     (array_ptr [j]) = (array_ptr [i]);
  385.     (array_ptr [i]) = Temp;
  386.       }
  387.   }
  388.   PRIMITIVE_RETURN (UNSPECIFIC);
  389. }
  390.  
  391. DEFINE_PRIMITIVE ("ARRAY-TIME-REVERSE!", Prim_array_time_reverse, 1, 1, 0)
  392. {
  393.   void C_Array_Time_Reverse ();
  394.   PRIMITIVE_HEADER (1);
  395.   CHECK_ARG (1, ARRAY_P);
  396.   C_Array_Time_Reverse
  397.     ((ARRAY_CONTENTS (ARG_REF (1))), (ARRAY_LENGTH (ARG_REF (1))));
  398.   PRIMITIVE_RETURN (UNSPECIFIC);
  399. }
  400.  
  401. /* time-reverse
  402.    x[0] remains fixed. (time=0)
  403.    x[i] swapped with x[n-i]. (mirror image around x[0]) */
  404.  
  405. void
  406. C_Array_Time_Reverse (x,n)
  407.      REAL *x;
  408.      long n;
  409. { long i, ni, n2;
  410.   REAL xt;
  411.   if ((n % 2) == 0)        /* even length */
  412.   { n2 = (n/2);
  413.     for (i=1; i<n2; i++)    /* i=1,2,..,n/2-1 */
  414.     {  ni = n-i;
  415.        xt    = x[i];
  416.        x[i]  = x[ni];
  417.        x[ni] = xt; }}
  418.   else                /* odd length */
  419.   { n2 = (n+1)/2;        /* (n+1)/2 = (n-1)/2 + 1 */
  420.     for (i=1; i<n2; i++)    /* i=1,2,..,(n-1)/2 */
  421.     {  ni = n-i;
  422.        xt   = x[i];
  423.        x[i] = x[ni];
  424.        x[ni] = xt; }}
  425. }
  426.  
  427. /* The following is smart
  428.    and avoids computation when offset or scale are degenerate 0,1 */
  429.  
  430. DEFINE_PRIMITIVE ("SUBARRAY-OFFSET-SCALE!", Prim_subarray_offset_scale, 5, 5, 0)
  431. {
  432.   long i, at, m,mplus;
  433.   REAL *a, offset,scale;
  434.   PRIMITIVE_HEADER (5);
  435.   CHECK_ARG (1, ARRAY_P);
  436.   CHECK_ARG (2, FIXNUM_P);
  437.   CHECK_ARG (3, FIXNUM_P);
  438.   a = ARRAY_CONTENTS(ARG_REF(1));
  439.   at = arg_nonnegative_integer(2); /*       at = starting index             */
  440.   m  = arg_nonnegative_integer(3); /*       m  = number of points to change */
  441.   mplus = at + m;
  442.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(3);
  443.   offset = (arg_real (4));
  444.   scale = (arg_real (5));
  445.   if ((offset == 0.0) && (scale == 1.0))
  446.     ;                /* be smart */
  447.   else if (scale == 0.0)
  448.     for (i=at; i<mplus; i++)  a[i] = offset;
  449.   else if (offset == 0.0)
  450.     for (i=at; i<mplus; i++)  a[i] = scale * a[i];
  451.   else if (scale == 1.0)
  452.     for (i=at; i<mplus; i++)  a[i] = offset + a[i];
  453.   else
  454.     for (i=at; i<mplus; i++)  a[i] = offset + scale * a[i];
  455.   PRIMITIVE_RETURN (UNSPECIFIC);
  456. }
  457.  
  458. DEFINE_PRIMITIVE ("COMPLEX-SUBARRAY-COMPLEX-SCALE!", Prim_complex_subarray_complex_scale, 6,6, 0)
  459. { long i, at,m,mplus;
  460.   REAL *a,*b;            /* (a,b) = (real,imag) arrays */
  461.   double temp, minus_y,  x, y;    /* (x,y) = (real,imag) scale */
  462.   PRIMITIVE_HEADER (6);
  463.   CHECK_ARG (1, ARRAY_P);
  464.   CHECK_ARG (2, ARRAY_P);
  465.   at = (arg_nonnegative_integer (3)); /* starting index */
  466.   m  = (arg_nonnegative_integer (4)); /* number of points to change */
  467.   mplus = at + m;
  468.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(4);
  469.   x = (arg_real_number (5));
  470.   y = (arg_real_number (6));
  471.   a = ARRAY_CONTENTS(ARG_REF(1));
  472.   b = ARRAY_CONTENTS(ARG_REF(2));
  473.   if ((ARRAY_LENGTH(ARG_REF(1))) != (ARRAY_LENGTH(ARG_REF(2))))
  474.     error_bad_range_arg(2);
  475.   if (x==0.0)            /* imaginary only */
  476.     if       (y==0.0)
  477.       for (i=at; i<mplus; i++)
  478.       { a[i] = 0.0;
  479.     b[i] = 0.0; }
  480.     else if  (y==1.0)
  481.       for (i=at; i<mplus; i++)
  482.       { temp = b[i];
  483.     b[i] = a[i];
  484.     a[i] = (-temp); }
  485.     else if  (y==-1.0)
  486.       for (i=at; i<mplus; i++)
  487.       { temp = b[i];
  488.     b[i] = (-a[i]);
  489.     a[i] = temp; }
  490.     else
  491.     { minus_y = (-y);
  492.       for (i=at; i<mplus; i++)
  493.       { temp =               y * ((double) a[i]);
  494.     a[i] = (REAL) (minus_y * ((double) b[i]));
  495.     b[i] = (REAL) temp; }}
  496.   else if (y==0.0)        /* real only */
  497.     if (x==1.0) ;
  498.     else for (i=at; i<mplus; i++)
  499.     { a[i] = (REAL) (x * ((double) a[i]));
  500.       b[i] = (REAL) (x * ((double) b[i])); }
  501.   else                /* full complex scale */
  502.     for (i=at; i<mplus; i++)
  503.     { temp =         ((double) a[i])*x - ((double) b[i])*y;
  504.       b[i] = (REAL) (((double) b[i])*x + ((double) a[i])*y);
  505.       a[i] = (REAL) temp; }
  506.   PRIMITIVE_RETURN (UNSPECIFIC);
  507. }
  508.  
  509. /* Accumulate
  510.    using combinators              *
  511.    corresponding type codes       1 */
  512.  
  513. DEFINE_PRIMITIVE ("COMPLEX-SUBARRAY-ACCUMULATE!", Prim_complex_subarray_accumulate, 6,6, 0)
  514. { long  at,m,mplus, tc, i;
  515.   REAL *a,*b;            /* (a,b) = (real,imag) input arrays */
  516.   REAL *c;    /* result = output array of length 2, holds a complex number */
  517.   double x, y, temp;
  518.   PRIMITIVE_HEADER (6);
  519.   CHECK_ARG (1, ARRAY_P);    /* a = input array (real) */
  520.   CHECK_ARG (2, ARRAY_P);    /* b = input array (imag) */
  521.   a = ARRAY_CONTENTS(ARG_REF(1));
  522.   b = ARRAY_CONTENTS(ARG_REF(2));
  523.   if ((ARRAY_LENGTH(ARG_REF(1))) != (ARRAY_LENGTH(ARG_REF(2))))
  524.     error_bad_range_arg(2);
  525.   tc = arg_nonnegative_integer(3); /*       tc = type code 0 or 1            */
  526.   at = arg_nonnegative_integer(4); /*       at = starting index              */
  527.   m  = arg_nonnegative_integer(5); /*       m  = number of points to process */
  528.   CHECK_ARG (6, ARRAY_P);    /* c = output array of length 2 */
  529.   c = ARRAY_CONTENTS(ARG_REF(6));
  530.   if ((ARRAY_LENGTH(ARG_REF(6))) != 2) error_bad_range_arg(6);
  531.   mplus = at + m;
  532.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(5);
  533.   if (tc==1)
  534.   { x = 1.0;            /* real part of accumulator */
  535.     y = 0.0;            /* imag part of accumulator */
  536.     for (i=at;i<mplus;i++)
  537.     { temp = ((double) a[i])*x - ((double) b[i])*y;
  538.       y    = ((double) b[i])*x + ((double) a[i])*y;
  539.       x    = temp; }
  540.   }
  541.   else
  542.     error_bad_range_arg(3);
  543.   c[0] = ((REAL) x);        /* mechanism for returning complex number */
  544.   c[1] = ((REAL) y);        /* do not use lists, avoid heap pointer   */
  545.   PRIMITIVE_RETURN (UNSPECIFIC);
  546. }
  547.  
  548. DEFINE_PRIMITIVE ("CS-ARRAY-TO-COMPLEX-ARRAY!", Prim_cs_array_to_complex_array, 3, 3, 0)
  549. { long n,n2,n2_1, i;
  550.   REAL *a, *b,*c;
  551.   PRIMITIVE_HEADER (3);
  552.   CHECK_ARG (1, ARRAY_P);
  553.   CHECK_ARG (2, ARRAY_P);
  554.   CHECK_ARG (3, ARRAY_P);
  555.   a = ARRAY_CONTENTS(ARG_REF(1));
  556.   n = ARRAY_LENGTH(ARG_REF(1));
  557.   b = ARRAY_CONTENTS(ARG_REF(2));
  558.   c = ARRAY_CONTENTS(ARG_REF(3));
  559.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  560.   if (n!=(ARRAY_LENGTH(ARG_REF(3)))) error_bad_range_arg(3);
  561.   b[0] = a[0];
  562.   c[0] = 0.0;
  563.   n2 = n/2;            /* integer division truncates down */
  564.   n2_1 = n2+1;
  565.   if (2*n2 == n)        /* even length, n2 is only real */
  566.   { b[n2]  = a[n2];  c[n2]  = 0.0; }
  567.   else /* odd length, make the loop include the n2 index */
  568.   { n2   = n2+1;
  569.     n2_1 = n2; }
  570.   for (i=1; i<n2; i++)   { b[i] = a[i];
  571.                c[i] = a[n-i]; }
  572.   for (i=n2_1; i<n; i++) { b[i] =  a[n-i];
  573.                c[i] = (-a[i]); }
  574.   PRIMITIVE_RETURN (UNSPECIFIC);
  575. }
  576.  
  577. DEFINE_PRIMITIVE ("CS-ARRAY-MULTIPLY-INTO-SECOND-ONE!", Prim_cs_array_multiply_into_second_one, 2, 2, 0)
  578. { long n,n2;
  579.   REAL *a, *b;
  580.   void cs_array_multiply_into_second_one();
  581.   PRIMITIVE_HEADER (2);
  582.   CHECK_ARG (1, ARRAY_P);
  583.   CHECK_ARG (2, ARRAY_P);
  584.   a = ARRAY_CONTENTS(ARG_REF(1));
  585.   n = ARRAY_LENGTH(ARG_REF(1));
  586.   b = ARRAY_CONTENTS(ARG_REF(2));
  587.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  588.   n2 = n/2;            /* integer division truncates down */
  589.   cs_array_multiply_into_second_one(a,b, n,n2);
  590.   PRIMITIVE_RETURN (UNSPECIFIC);
  591. }
  592.  
  593. void
  594. cs_array_multiply_into_second_one (a,b, n,n2)
  595.      REAL *a, *b;
  596.      long n,n2;
  597. {
  598.   REAL temp;
  599.   long i,ni;
  600.   b[0]   = a[0]  * b[0];
  601.   if (2*n2 == n)        /* even length, n2 is only real */
  602.     b[n2]  = a[n2] * b[n2];
  603.   else
  604.     n2 = n2+1; /* odd length, make the loop include the n2 index */
  605.   for (i=1; i<n2; i++)
  606.     {
  607.       ni = n-i;
  608.       temp   = a[i]*b[i]   -  a[ni]*b[ni]; /* real part */
  609.       b[ni]  = a[i]*b[ni]  +  a[ni]*b[i]; /*  imag part */
  610.       b[i]   = temp;
  611.     }
  612. }
  613.  
  614. DEFINE_PRIMITIVE ("CS-ARRAY-DIVIDE-INTO-XXX!", Prim_cs_array_divide_into_xxx, 4, 4, 0)
  615. {
  616.   long n,n2, one_or_two;
  617.   REAL *a, *b, inf;
  618.   void cs_array_divide_into_z();
  619.   PRIMITIVE_HEADER (4);
  620.   CHECK_ARG (1, ARRAY_P);
  621.   CHECK_ARG (2, ARRAY_P);
  622.   inf = (arg_real (3));
  623.   /* where to store result of division */
  624.   one_or_two = (arg_nonnegative_integer (4));
  625.   a = ARRAY_CONTENTS(ARG_REF(1));
  626.   b = ARRAY_CONTENTS(ARG_REF(2));
  627.   n = ARRAY_LENGTH(ARG_REF(1));
  628.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  629.   n2 = n/2;            /* integer division truncates down */
  630.   if (one_or_two == 1)
  631.     cs_array_divide_into_z(a,b, a,  n,n2, inf);
  632.   else if (one_or_two == 2)
  633.     cs_array_divide_into_z(a,b, b,  n,n2, inf);
  634.   else
  635.     error_bad_range_arg(4);
  636.   PRIMITIVE_RETURN (UNSPECIFIC);
  637. }
  638.  
  639. void
  640. cs_array_divide_into_second_one (a,b, n,n2,inf)    /* used in image.c */
  641.      REAL *a,*b, inf;
  642.      long n,n2;
  643. {
  644.   void cs_array_divide_into_z ();
  645.   cs_array_divide_into_z (a,b, b, n,n2,inf);
  646. }
  647.  
  648. void
  649. cs_array_divide_into_z (a,b, z, n,n2, inf) /* z can be either a or b */
  650.      REAL *a,*b,*z, inf;
  651.      long n,n2;
  652. { long i,ni;
  653.   REAL temp, radius;
  654.  
  655.   if (b[0] == 0.0)
  656.     if (a[0] == 0.0) z[0] = 1.0;
  657.     else             z[0] = a[0] * inf;
  658.   else               z[0] = a[0] / b[0];
  659.  
  660.   if (2*n2 == n)        /* even length, n2 is only real */
  661.     if (b[n2] == 0.0)
  662.       if (a[n2] == 0.0) z[n2] = 1.0;
  663.       else              z[n2] = a[n2] * inf;
  664.     else                z[n2] = a[n2] / b[n2];
  665.   else
  666.     n2 = n2+1; /* odd length, make the loop include the n2 index */
  667.  
  668.   for (i=1; i<n2; i++)
  669.   { ni = n-i;
  670.     radius = b[i]*b[i] + b[ni]*b[ni]; /* b^2 denominator = real^2 + imag^2 */
  671.  
  672.     if (radius == 0.0) {
  673.       if (a[i]  == 0.0) z[i]  = 1.0;
  674.       else              z[i]  = a[i] * inf;
  675.       if (a[ni] == 0.0) z[ni] = 1.0;
  676.       else              z[ni] = a[ni] * inf; }
  677.     else {
  678.       temp  = a[i]*b[i]    +  a[ni]*b[ni];
  679.       z[ni] = (a[ni]*b[i]  -  a[i]*b[ni]) / radius; /* imag part */
  680.       z[i]  = temp                        / radius; /* real part */
  681.     }}
  682. }
  683.  
  684. /* ARRAY-UNARY-FUNCTION!
  685.    apply unary-function elementwise on array
  686.    Available functions : */
  687.  
  688. void
  689. REALabs (a,b)
  690.      REAL *a,*b;
  691. {
  692.   (*b) = ( (REAL) fabs( (double) (*a)) );
  693. }
  694.  
  695. void
  696. REALexp (a,b)
  697.      REAL *a,*b;
  698. {
  699.   fast double y;
  700.   if ((y = exp((double) (*a))) == HUGE)
  701.     error_bad_range_arg (1);    /* OVERFLOW */
  702.   (*b) = ((REAL) y);
  703. }
  704.  
  705. void
  706. REALlog (a,b)
  707.      REAL *a,*b;
  708. {
  709.   if ((*a) < 0.0)
  710.     error_bad_range_arg(1);    /* log(negative) */
  711.   (*b) = ( (REAL) log( (double) (*a)) );
  712. }
  713.  
  714. void
  715. REALtruncate (a,b)
  716.      REAL *a,*b;        /* towards zero */
  717. {
  718.   double integral_part, modf();
  719.   modf( ((double) (*a)), &integral_part);
  720.   (*b) = ( (REAL) integral_part);
  721. }
  722.  
  723. void
  724. REALround (a,b)
  725.      REAL *a,*b;        /* towards nearest integer */
  726. {
  727.   double integral_part, modf();
  728.   if ((*a) >= 0.0)        /* It may be faster to look at the sign
  729.                    of mantissa, and dispatch */
  730.     modf( ((double) ((*a)+0.5)), &integral_part);
  731.   else
  732.     modf( ((double) ((*a)-0.5)), &integral_part);
  733.   (*b) = ( (REAL) integral_part);
  734. }
  735.  
  736. void
  737. REALsquare (a,b)
  738.      REAL *a,*b;
  739. {
  740.   (*b) = ( (REAL) ((*a) * (*a)) );
  741. }
  742.  
  743. void
  744. REALsqrt (a,b)
  745.      REAL *a,*b;
  746. {
  747.   if ((*a) < 0.0)
  748.     error_bad_range_arg(1);    /* sqrt(negative) */
  749.   (*b) = ( (REAL) sqrt( (double) (*a)) );
  750. }
  751.  
  752. void
  753. REALsin (a,b)
  754.      REAL *a,*b;
  755. {
  756.   (*b) = ( (REAL) sin( (double) (*a)) );
  757. }
  758.  
  759. void
  760. REALcos (a,b)
  761.      REAL *a,*b;
  762. {
  763.   (*b) = ( (REAL) cos( (double) (*a)) );
  764. }
  765.  
  766. void
  767. REALtan (a,b)
  768.      REAL *a,*b;
  769. {
  770.   (*b) = ( (REAL) tan( (double) (*a)) );
  771. }
  772.  
  773. void
  774. REALasin (a,b)
  775.      REAL *a,*b;
  776. {
  777.   (*b) = ( (REAL) asin( (double) (*a)) );
  778. }
  779.  
  780. void
  781. REALacos (a,b)
  782.      REAL *a,*b;
  783. {
  784.   (*b) = ( (REAL) acos( (double) (*a)) );
  785. }
  786.  
  787. void
  788. REALatan (a,b)
  789.      REAL *a,*b;
  790. {
  791.   (*b) = ( (REAL) atan( (double) (*a)) );
  792. }
  793.  
  794. void
  795. REALgamma (a,b)
  796.      REAL *a,*b;
  797. {
  798.   fast double y;
  799.   if ((y = gamma(((double) (*a)))) > LN_MAXDOUBLE)
  800.     error_bad_range_arg(1);    /* gamma( non-positive integer ) */
  801.   (*b) = ((REAL) (signgam * exp(y))); /* see HPUX Section 3 */
  802. }
  803.  
  804. void
  805. REALerf (a,b)
  806.      REAL *a,*b;
  807. {
  808.   (*b) = ( (REAL) erf((double) (*a)) );
  809. }
  810.  
  811. void
  812. REALerfc (a,b)
  813.      REAL *a,*b;
  814. {
  815.   (*b) = ( (REAL) erfc((double) (*a)) );
  816. }
  817.  
  818. void
  819. REALbessel1 (order,a,b)        /* Bessel of first kind */
  820.      long order;
  821.      REAL *a,*b;
  822. {
  823.   if (order == 0)
  824.     (*b) = ( (REAL) j0((double) (*a)) );
  825.   if (order == 1)
  826.     (*b) = ( (REAL) j1((double) (*a)) );
  827.   else
  828.     (*b) = ( (REAL) jn(((int) order), ((double) (*a))) );
  829. }
  830.  
  831. void
  832. REALbessel2 (order,a,b)        /* Bessel of second kind */
  833.      long order;
  834.      REAL *a,*b;
  835. {
  836.   if ((*a) <= 0.0)
  837.     error_bad_range_arg(1);    /* Blows Up */
  838.   if (order == 0)
  839.     (*b) = ( (REAL) y0((double) (*a)) );
  840.   if (order == 1)
  841.     (*b) = ( (REAL) y1((double) (*a)) );
  842.   else
  843.     (*b) = ( (REAL) yn(((int) order), ((double) (*a))) );
  844. }
  845.  
  846. /* Table to store the available unary-functions.
  847.    Also some binary functions at the end -- not available right now.
  848.    The (1 and 2)s denote the numofargs (1 for unary 2 for binary) */
  849.  
  850. struct array_func_table
  851. {
  852.   long numofargs;
  853.   void (*func)();
  854. }
  855. Array_Function_Table [] =
  856. {
  857.   1, REALabs,            /*0*/
  858.   1, REALexp,            /*1*/
  859.   1, REALlog,            /*2*/
  860.   1, REALtruncate,        /*3*/
  861.   1, REALround,            /*4*/
  862.   1, REALsquare,        /*5*/
  863.   1, REALsqrt,            /*6*/
  864.   1, REALsin,            /*7*/
  865.   1, REALcos,            /*8*/
  866.   1, REALtan,            /*9*/
  867.   1, REALasin,            /*10*/
  868.   1, REALacos,            /*11*/
  869.   1, REALatan,            /*12*/
  870.   1, REALgamma,            /*13*/
  871.   1, REALerf,            /*14*/
  872.   1, REALerfc,            /*15*/
  873.   2, REALbessel1,        /*16*/
  874.   2, REALbessel2        /*17*/
  875.   };
  876.  
  877. #define MAX_ARRAY_FUNCTC 17
  878.  
  879. /* array-unary-function!    could be called        array-operation-1!
  880.    following the naming convention for other similar procedures
  881.    but it is specialized to mappings only, so we have special name. */
  882.  
  883. DEFINE_PRIMITIVE ("ARRAY-UNARY-FUNCTION!", Prim_array_unary_function, 2,2, 0)
  884. {
  885.   long n, i;
  886.   REAL *a,*b;
  887.   long tc;
  888.   void (*f)();
  889.   PRIMITIVE_HEADER (2);
  890.   CHECK_ARG (1, ARRAY_P);    /*      a  = input (and output) array    */
  891.   CHECK_ARG (2, FIXNUM_P);    /*      tc = type code                   */
  892.   tc = arg_nonnegative_integer(2);
  893.   if (tc > MAX_ARRAY_FUNCTC) error_bad_range_arg(2);
  894.   f = ((Array_Function_Table[tc]).func);
  895.   if (1 != (Array_Function_Table[tc]).numofargs) error_wrong_type_arg(2);
  896.   /* check it is a unary function */
  897.   a = ARRAY_CONTENTS(ARG_REF(1));
  898.   b = a;
  899.   n = ARRAY_LENGTH(ARG_REF(1));
  900.   for (i=0; i<n; i++)
  901.     (*f) ( &(a[i]), &(b[i]) );    /* a into b */
  902.   PRIMITIVE_RETURN (UNSPECIFIC);
  903. }
  904.  
  905. /* Accumulate
  906.    using combinators              +  or  *
  907.    corresponding type codes       0      1 */
  908.  
  909. DEFINE_PRIMITIVE ("SUBARRAY-ACCUMULATE", Prim_subarray_accumulate, 4,4, 0)
  910. {
  911.   long at,m,mplus, tc, i;
  912.   REAL *a;
  913.   double result;
  914.   PRIMITIVE_HEADER (4);
  915.   CHECK_ARG (1, ARRAY_P);    /*           a = input array                 */
  916.   a  = ARRAY_CONTENTS(ARG_REF(1));
  917.   tc = arg_nonnegative_integer(2); /*       tc = type code 0 or 1            */
  918.   at = arg_nonnegative_integer(3); /*       at = starting index              */
  919.   m  = arg_nonnegative_integer(4); /*       m  = number of points to process */
  920.   mplus = at + m;
  921.   if (mplus > (ARRAY_LENGTH(ARG_REF(1)))) error_bad_range_arg(4);
  922.   if (tc == 0)
  923.     {
  924.       result = 0.0;
  925.       for (i=at;i<mplus;i++)
  926.     result = result + ((double) a[i]);
  927.     }
  928.   else if (tc == 1)
  929.     {
  930.       result = 1.0;
  931.       for (i=at;i<mplus;i++)
  932.     result = result * ((double) a[i]);
  933.     }
  934.   else
  935.     error_bad_range_arg (2);
  936.   PRIMITIVE_RETURN (double_to_flonum (result));
  937. }
  938.  
  939. /* The following searches for value within tolerance
  940.    starting from index=from in array.
  941.    Returns first index where match occurs (useful for finding zeros). */
  942.  
  943. DEFINE_PRIMITIVE ("ARRAY-SEARCH-VALUE-TOLERANCE-FROM", Prim_array_search_value_tolerance_from, 4, 4, 0)
  944. {
  945.   SCHEME_OBJECT array;
  946.   fast long length;
  947.   fast REAL * a;
  948.   fast REAL value;        /* value to search for */
  949.   fast double tolerance;    /* tolerance allowed */
  950.   PRIMITIVE_HEADER (4);
  951.   CHECK_ARG (1, ARRAY_P);
  952.   array = (ARG_REF (1));
  953.   length = (ARRAY_LENGTH (array));
  954.   a = (ARRAY_CONTENTS (array));
  955.   value = (arg_real (2));
  956.   tolerance = (arg_real (3));
  957.   {
  958.     fast long i;
  959.     for (i = (arg_index_integer (4, length)); i<length; i+=1)
  960.       if (tolerance >= (fabs ((double) ((a [i]) - value))))
  961.     PRIMITIVE_RETURN (LONG_TO_UNSIGNED_FIXNUM (i));
  962.   }
  963.   PRIMITIVE_RETURN (SHARP_F);
  964. }
  965.  
  966. DEFINE_PRIMITIVE ("SUBARRAY-MIN-MAX-INDEX", Prim_subarray_min_max_index, 3, 3, 0)
  967. {
  968.   PRIMITIVE_HEADER (3);
  969.   CHECK_ARG (1, ARRAY_P);
  970.   {
  971.     REAL * a = (ARRAY_CONTENTS (ARG_REF (1)));
  972.     long at = (arg_nonnegative_integer (2)); /* starting index */
  973.     long m  = (arg_nonnegative_integer (3)); /* number of points to process */
  974.     long mplus = (at + m);
  975.     long nmin;
  976.     long nmax;
  977.     if (mplus > (ARRAY_LENGTH (ARG_REF (1))))
  978.       error_bad_range_arg (3);
  979.     
  980.     C_Array_Find_Min_Max ((& (a [at])), m, (&nmin), (&nmax));
  981.     nmin = nmin + at;        /* offset appropriately */
  982.     nmax = nmax + at;
  983.     
  984.     PRIMITIVE_RETURN
  985.       (cons ((LONG_TO_FIXNUM (nmin)),
  986.          (cons ((LONG_TO_FIXNUM (nmax)),
  987.             EMPTY_LIST))));
  988.   }
  989. }
  990.  
  991. void
  992. C_Array_Find_Min_Max (x, n, nmin, nmax)
  993.      fast REAL * x;
  994.      fast long n;
  995.      long * nmin;
  996.      long * nmax;
  997. { REAL *xold = x;
  998.   register REAL xmin, xmax;
  999.   register long nnmin, nnmax;
  1000.   register long count;
  1001.  
  1002.   nnmin = nnmax = 0;
  1003.   xmin = xmax = *x++;
  1004.   n--;
  1005.   count = 1;
  1006.   if(n>0)
  1007.   {
  1008.     do {
  1009.       if(*x < xmin) {
  1010.     nnmin = count++ ;
  1011.     xmin = *x++ ;
  1012.       } else if(*x > xmax) {
  1013.     nnmax = count++ ;
  1014.     xmax = *x++ ;
  1015.       } else {
  1016.     count++ ;
  1017.     x++ ;
  1018.       }
  1019.     } while( --n > 0 ) ;
  1020.   }
  1021.   *nmin = nnmin ;
  1022.   *nmax = nnmax ;
  1023. }
  1024.  
  1025.  
  1026. /* array-average
  1027.    can be done with (array-reduce +) and division by array-length.
  1028.    But there is also this C primitive.
  1029.    Keep it around, may be useful someday. */
  1030.  
  1031. /* Computes the average in pieces, so as to reduce
  1032.    roundoff smearing in cumulative sum.
  1033.    example= first huge positive numbers, then small nums,
  1034.    then huge negative numbers. */
  1035.  
  1036. static void
  1037. C_Array_Find_Average (Array, Length, pAverage)
  1038.      long Length;
  1039.      REAL * Array;
  1040.      REAL * pAverage;
  1041. {
  1042.   long i;
  1043.   long array_index;
  1044.   REAL average_n, sum;
  1045.  
  1046.   average_n = 0.0;
  1047.   array_index = 0;
  1048.   while (array_index < Length)
  1049.     {
  1050.       sum = 0.0;
  1051.       for (i=0;((array_index<Length) && (i<2000));i++) {
  1052.     sum += Array[array_index];
  1053.     array_index++;
  1054.       }
  1055.       average_n += (sum / ((REAL) Length));
  1056.     }
  1057.   (*pAverage) = average_n;
  1058.   return;
  1059. }
  1060.  
  1061. DEFINE_PRIMITIVE ("ARRAY-AVERAGE", Prim_array_find_average, 1, 1, 0)
  1062. {
  1063.   SCHEME_OBJECT array;
  1064.   REAL average;
  1065.   PRIMITIVE_HEADER (1);
  1066.   CHECK_ARG (1, ARRAY_P);
  1067.   array = (ARG_REF (1));
  1068.   C_Array_Find_Average
  1069.     ((ARRAY_CONTENTS (array)),
  1070.      (ARRAY_LENGTH (array)),
  1071.      (&average));
  1072.   PRIMITIVE_RETURN (double_to_flonum ((double) average));
  1073. }
  1074.  
  1075. void
  1076. C_Array_Make_Histogram (Array, Length, Histogram, npoints)
  1077.      REAL Array[], Histogram[];
  1078.      long Length, npoints;
  1079. {
  1080.   REAL Max, Min, Offset, Scale;
  1081.   long i, nmin, nmax, index;
  1082.   C_Array_Find_Min_Max (Array, Length, (&nmin), (&nmax));
  1083.   Min = (Array [nmin]);
  1084.   Max = (Array [nmax]);
  1085.   Find_Offset_Scale_For_Linear_Map
  1086.     (Min, Max, 0.0, ((REAL) npoints), (&Offset), (&Scale));
  1087.   for (i = 0; (i < npoints); i += 1)
  1088.     (Histogram [i]) = 0.0;
  1089.   for (i = 0; (i < Length); i += 1)
  1090.     {
  1091.       /* Everything from 0 to 1 maps to bin 0, and so on */
  1092.       index = ((long) (floor ((double) ((Scale * (Array [i])) + Offset))));
  1093.       /* max that won't floor to legal array index */
  1094.       if (index == npoints)
  1095.     index = (index - 1);
  1096.       (Histogram [index]) += 1.0;
  1097.     }
  1098.   return;
  1099. }
  1100.  
  1101. DEFINE_PRIMITIVE ("ARRAY-MAKE-HISTOGRAM", Prim_array_make_histogram, 2, 2, 0)
  1102. {
  1103.   PRIMITIVE_HEADER (2);
  1104.   CHECK_ARG (1, ARRAY_P);
  1105.   {
  1106.     fast SCHEME_OBJECT array = (ARG_REF (1));
  1107.     long length = (ARRAY_LENGTH (array));
  1108.     long npoints = (arg_integer_in_range (2, 1, ((2 * length) + 1)));
  1109.     SCHEME_OBJECT result = (allocate_array (npoints));
  1110.     C_Array_Make_Histogram
  1111.       ((ARRAY_CONTENTS (array)),
  1112.        length,
  1113.        (ARRAY_CONTENTS (result)),
  1114.        npoints);
  1115.     PRIMITIVE_RETURN (result);
  1116.   }
  1117. }
  1118.  
  1119. /* The following geometrical map is slightly tricky. */
  1120. void
  1121. Find_Offset_Scale_For_Linear_Map (Min, Max, New_Min, New_Max, Offset, Scale)
  1122.      REAL Min, Max, New_Min, New_Max, *Offset, *Scale;
  1123. {
  1124.   if (Min != Max)
  1125.     {
  1126.       (*Scale)  = ((New_Max - New_Min) / (Max - Min));
  1127.       (*Offset) = (New_Min - ((*Scale) * Min));
  1128.     }
  1129.   else
  1130.     {
  1131.       (*Scale) =
  1132.     ((Max == 0.0)
  1133.      ? 0.0
  1134.      : (0.25 * (mabs ((New_Max - New_Min) / Max))));
  1135.       (*Offset) = ((New_Max + New_Min) / 2.0);
  1136.     }
  1137.   return;
  1138. }
  1139.  
  1140.  
  1141. DEFINE_PRIMITIVE ("ARRAY-CLIP-MIN-MAX!", Prim_array_clip_min_max, 3, 3, 0)
  1142. {
  1143.   PRIMITIVE_HEADER (3);
  1144.   CHECK_ARG (1, ARRAY_P);
  1145.   {
  1146.     SCHEME_OBJECT array = (ARG_REF (1));
  1147.     REAL xmin = (arg_real (2));
  1148.     REAL xmax = (arg_real (3));
  1149.     long Length = (ARRAY_LENGTH (array));
  1150.     REAL * From_Here = (ARRAY_CONTENTS (array));
  1151.     REAL * To_Here = From_Here;
  1152.     long i;
  1153.     if (xmin > xmax)
  1154.       error_bad_range_arg (3);
  1155.     for (i = 0; (i < Length); i += 1)
  1156.       {
  1157.     if ((*From_Here) < xmin)
  1158.       (*To_Here++) = xmin;
  1159.     else if ((*From_Here) > xmax)
  1160.       (*To_Here++) = xmax;
  1161.     else
  1162.       (*To_Here++) = (*From_Here);
  1163.     From_Here += 1;
  1164.       }
  1165.   }
  1166.   PRIMITIVE_RETURN (UNSPECIFIC);
  1167. }
  1168.  
  1169. /* complex-array-operation-1!
  1170.    groups together procedures that use 1 complex-array
  1171.    and store the result in place */
  1172.  
  1173. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-1!", Prim_complex_array_operation_1, 3,3, 0)
  1174. { long n, i, opcode;
  1175.   REAL *a, *b;
  1176.   void complex_array_to_polar(), complex_array_exp(), complex_array_sqrt();
  1177.   void complex_array_sin(), complex_array_cos();
  1178.   void complex_array_asin(), complex_array_acos(), complex_array_atan();
  1179.   PRIMITIVE_HEADER (3);
  1180.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1181.   CHECK_ARG (2, ARRAY_P);    /* input array -- n      real part         */
  1182.   CHECK_ARG (3, ARRAY_P);    /* input array -- n      imag part         */
  1183.   n = ARRAY_LENGTH(ARG_REF(2));
  1184.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1185.   a  = ARRAY_CONTENTS(ARG_REF(2)); /*  real part */
  1186.   b  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag part */
  1187.   opcode = arg_nonnegative_integer(1);
  1188.   if (opcode==1)
  1189.     complex_array_to_polar(a,b,n);
  1190.   else if (opcode==2)
  1191.     complex_array_exp(a,b,n);
  1192.   else if (opcode==3)
  1193.     complex_array_sqrt(a,b,n);
  1194.  
  1195.   else if (opcode==4)
  1196.     complex_array_sin(a,b,n);
  1197.   else if (opcode==5)
  1198.     complex_array_cos(a,b,n);
  1199.   /* for tan(z) use sin(z)/cos(z) */
  1200.   
  1201.   else if (opcode==6)
  1202.     complex_array_asin(a,b,n);
  1203.   else if (opcode==7)
  1204.     complex_array_acos(a,b,n);
  1205.   else if (opcode==8)
  1206.     complex_array_atan(a,b,n);
  1207.   
  1208.   else
  1209.     error_bad_range_arg(1);    /* illegal opcode */
  1210.   PRIMITIVE_RETURN (UNSPECIFIC);
  1211. }
  1212.  
  1213. void
  1214. complex_array_to_polar (a,b,n)
  1215.      REAL *a,*b;
  1216.      long n;
  1217. {
  1218.   long i;
  1219.   double x,y, temp;
  1220.   for (i=0; i<n; i++)
  1221.     {
  1222.       x = (double) a[i];
  1223.       y = (double) b[i];
  1224.       temp = sqrt(x*x + y*y);
  1225.       if (temp == 0.0)
  1226.     b[i] = 0.0;        /* choose angle = 0    for x,y=0,0 */
  1227.       else
  1228.     b[i] = (REAL) atan2(y,x);
  1229.       a[i]   = (REAL) temp;
  1230.     }
  1231. }
  1232.  
  1233. void
  1234. complex_array_exp (a,b,n)
  1235.      REAL *a,*b;
  1236.      long n;
  1237. {
  1238.   long i;
  1239.   double x,y, temp;
  1240.  
  1241.   for (i=0; i<n; i++)
  1242.     {
  1243.       x = (double) a[i];
  1244.       y = (double) b[i];
  1245.       if ((temp = exp(x)) == HUGE) error_bad_range_arg(2); /* overflow */
  1246.       a[i] = (REAL) (temp*cos(y));
  1247.       b[i] = (REAL) (temp*sin(y));
  1248.     }
  1249. }
  1250.  
  1251. void
  1252. complex_array_sqrt (a,b,n)
  1253.      REAL *a,*b;
  1254.      long n;
  1255. {
  1256.   long i;
  1257.   double x,y, r;
  1258.  
  1259.   for (i=0; i<n; i++)
  1260.     {
  1261.       x = (double) a[i];
  1262.       y = (double) b[i];
  1263.       r = sqrt( x*x + y*y);
  1264.       a[i] = sqrt((r+x)/2.0);
  1265.       if (y>=0.0)
  1266.     b[i] =  sqrt((r-x)/2.0); /* choose principal root */
  1267.       else            /* see Abramowitz (p.17 3.7.27) */
  1268.     b[i] = -sqrt((r-x)/2.0);
  1269.     }
  1270. }
  1271.  
  1272. void
  1273. complex_array_sin (a,b,n)
  1274.      REAL *a,*b;
  1275.      long n;
  1276. {
  1277.   long i;
  1278.   double x, ey,fy;
  1279.   REAL temp;
  1280.  
  1281.   for (i=0; i<n; i++)
  1282.     {
  1283.       x = (double) a[i];
  1284.       ey = exp((double) b[i]);    /* radius should be small to avoid overflow */
  1285.       fy = 1.0/ey;        /* exp(-y) */
  1286.       /* expanded (e(iz)-e(-iz))*(-.5i) formula */
  1287.       temp = (REAL) (sin(x) * (ey + fy) * 0.5);
  1288.       /* see my notes in Abram.p.71 */
  1289.       b[i] = (REAL) (cos(x) * (ey - fy) * 0.5);
  1290.       a[i] = temp;
  1291.     }
  1292. }
  1293.  
  1294. void
  1295. complex_array_cos (a,b,n)
  1296.      REAL *a,*b;
  1297.      long n;
  1298. {
  1299.   long i;
  1300.   double x, ey,fy;
  1301.   REAL temp;
  1302.  
  1303.   for (i=0; i<n; i++)
  1304.     {
  1305.       x = (double) a[i];
  1306.       ey = exp((double) b[i]);    /* radius should be small to avoid overflow */
  1307.       fy = 1.0/ey;        /* exp(-y) */
  1308.       /* expanded (e(iz)+e(-iz))*.5 formula */
  1309.       temp = (REAL) (cos(x) * (ey + fy) * 0.5);
  1310.       b[i] = (REAL) (sin(x) * (fy - ey) * 0.5); /* see my notes in Abram.p.71*/
  1311.       a[i] = temp;
  1312.     }
  1313. }
  1314.  
  1315.  
  1316. void
  1317. complex_array_asin (a,b,n)
  1318.      REAL *a,*b;
  1319.      long n;
  1320. { /* logarithmic formula as in R3.99, about 21ops plus log,atan - see my notes */
  1321.   long i; 
  1322.   double oldx,oldy, x,y, real,imag, r;
  1323.   
  1324.   for (i=0; i<n; i++)
  1325.   {
  1326.     oldx = (double) a[i];
  1327.     oldy = (double) b[i];
  1328.     
  1329.     x = 1.0 - oldx*oldx + oldy*oldy; /* 1 - z*z */
  1330.     y = -2.0 * oldx * oldy;
  1331.     
  1332.     r = sqrt(x*x + y*y);    /* sqrt(1-z*z)  */
  1333.     real = sqrt((r+x)/2.0);
  1334.     if (y>=0.0)
  1335.       imag =  sqrt((r-x)/2.0);    /* choose principal root */
  1336.     else            /* see Abramowitz (p.17 3.7.27) */
  1337.       imag = -sqrt((r-x)/2.0);
  1338.     
  1339.     real = real - oldy;        /* i*z + sqrt(...) */
  1340.     imag = imag + oldx;
  1341.     
  1342.     b[i] = (REAL) (- log (sqrt (real*real + imag*imag))); /* -i*log(...) */
  1343.     a[i] = (REAL) atan2( imag, real); /* chosen angle is okay 
  1344.                      Also 0/0 doesnot occur */
  1345.   }
  1346. }
  1347.  
  1348. void
  1349. complex_array_acos (a,b,n)
  1350.      REAL *a,*b;
  1351.      long n;
  1352. {
  1353.   long i;
  1354.  
  1355.   complex_array_asin (a,b,n);
  1356.   
  1357.   for (i=0; i<n; i++)
  1358.     {
  1359.       a[i] = PI_OVER_2 - a[i];
  1360.       b[i] =           - b[i];
  1361.     }
  1362. }
  1363.   
  1364.  
  1365. void
  1366. complex_array_atan (a,b,n)
  1367.      REAL *a,*b;
  1368.      long n;
  1369. { /* logarithmic formula, expanded, simplified - see my notes */
  1370.   long i; 
  1371.   double x,y, xx, real,imag, d;
  1372.   
  1373.   for (i=0; i<n; i++)
  1374.   {
  1375.     x = (double) a[i];
  1376.     y = (double) b[i];
  1377.     
  1378.     xx = x*x;
  1379.     imag = 1.0 + y;        /* temp var */
  1380.     d  = xx + imag*imag;
  1381.     
  1382.     real = (1 - y*y - xx) / d;
  1383.     imag = (2.0 * x)  / d;
  1384.     
  1385.     b[i] = (REAL) ((log (sqrt (real*real + imag*imag))) / -2.0);
  1386.     a[i] = (atan2 (imag,real)) / 2.0;
  1387.   }
  1388. }
  1389.  
  1390.  
  1391. /* complex-array-operation-1b!
  1392.    groups together procedures that use 1 complex-array & 1 number
  1393.    and store the result in place (e.g. invert 1/x) */
  1394.  
  1395. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-1B!", Prim_complex_array_operation_1b, 4,4, 0)
  1396. {
  1397.   long n, i, opcode;
  1398.   REAL *a, *b, inf;
  1399.   void complex_array_invert ();
  1400.   PRIMITIVE_HEADER (4);
  1401.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1402.   CHECK_ARG (2, ARRAY_P);    /* input array -- n      real part         */
  1403.   CHECK_ARG (3, ARRAY_P);    /* input array -- n      imag part         */
  1404.   inf = (arg_real (4));        /* User-Provided Infinity */
  1405.   n = ARRAY_LENGTH(ARG_REF(2));
  1406.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1407.   a  = ARRAY_CONTENTS(ARG_REF(2)); /*  real part */
  1408.   b  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag part */
  1409.   opcode = arg_nonnegative_integer(1);
  1410.   if (opcode==1)
  1411.     complex_array_invert(a,b, n, inf);  /* performs 1/x */
  1412.   else if (opcode==2)
  1413.     error_bad_range_arg(1);    /* illegal opcode */
  1414.   else
  1415.     error_bad_range_arg(1);    /* illegal opcode */
  1416.   PRIMITIVE_RETURN (UNSPECIFIC);
  1417. }
  1418.  
  1419. void
  1420. complex_array_invert (a,b, n, inf)
  1421.      REAL *a,*b, inf;
  1422.      long n;
  1423. {
  1424.   long i;
  1425.   double x,y, r;
  1426.   for (i=0; i<n; i++)
  1427.     {
  1428.       x = (double) a[i];
  1429.       y = (double) b[i];
  1430.       r = (x*x + y*y);
  1431.       if (r==0.0)
  1432.     {
  1433.       a[i] = inf;
  1434.       b[i] = inf;
  1435.     }
  1436.       else
  1437.     {
  1438.       a[i] = (REAL)  x/r;
  1439.       b[i] = (REAL) -y/r;
  1440.     }
  1441.     }
  1442. }
  1443.  
  1444. /* complex-array-operation-1a
  1445.    groups together procedures that use 1 complex-array
  1446.    and store result in a 3rd real array. */
  1447.  
  1448. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-1A", Prim_complex_array_operation_1a, 4,4, 0)
  1449. {
  1450.   long n, i, opcode;
  1451.   REAL *a, *b, *c;
  1452.   void complex_array_magnitude(), complex_array_angle();
  1453.   PRIMITIVE_HEADER (4);
  1454.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1455.   CHECK_ARG (2, ARRAY_P);    /* input array -- n      real part         */
  1456.   CHECK_ARG (3, ARRAY_P);    /* input array -- n      imag part         */
  1457.   CHECK_ARG (4, ARRAY_P);    /* output array -- n                       */
  1458.   n = ARRAY_LENGTH(ARG_REF(2));
  1459.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1460.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(4);
  1461.   a  = ARRAY_CONTENTS(ARG_REF(2)); /*  real part */
  1462.   b  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag part */
  1463.   c  = ARRAY_CONTENTS(ARG_REF(4)); /*  output    */
  1464.   opcode = arg_nonnegative_integer(1);
  1465.   if (opcode==1)
  1466.     complex_array_magnitude(a,b,c,n);
  1467.   else if (opcode==2)
  1468.     complex_array_angle(a,b,c,n);
  1469.   else
  1470.     error_bad_range_arg(1);    /* illegal opcode */
  1471.   PRIMITIVE_RETURN (UNSPECIFIC);
  1472. }
  1473.  
  1474. void
  1475. complex_array_magnitude (a,b,c,n)
  1476.      REAL *a,*b,*c;
  1477.      long n;
  1478. {
  1479.   long i;
  1480.   for (i=0; i<n; i++)
  1481.     c[i] = (REAL) sqrt( (double) a[i]*a[i] + b[i]*b[i] );
  1482. }
  1483.  
  1484. void
  1485. complex_array_angle (a,b,c,n)
  1486.      REAL *a,*b,*c;
  1487.      long n;
  1488. {
  1489.   long i;
  1490.   for (i=0; i<n; i++)
  1491.   {
  1492.     if ((a[i] == 0.0) && (b[i]==0.0))
  1493.       c[i] = 0.0;        /* choose angle=0 for point (0,0) */
  1494.     else
  1495.       c[i] = (REAL) atan2( (double) b[i], (double) a[i]);
  1496.     /* angle ==   -pi (exclusive) to +pi (inclusive) */
  1497.   }
  1498. }
  1499.  
  1500. DEFINE_PRIMITIVE ("CS-ARRAY-MAGNITUDE!", Prim_cs_array_magnitude, 1, 1, 0)
  1501. {
  1502.   long n, i;
  1503.   REAL *a;
  1504.   void cs_array_magnitude();
  1505.   PRIMITIVE_HEADER (1);
  1506.   CHECK_ARG (1, ARRAY_P);
  1507.   a = ARRAY_CONTENTS(ARG_REF(1)); /* input cs-array */
  1508.   n = ARRAY_LENGTH(ARG_REF(1));    /* becomes a standard array on return  */
  1509.   cs_array_magnitude(a,n);
  1510.   PRIMITIVE_RETURN (UNSPECIFIC);
  1511. }
  1512.  
  1513. /* result is a standard array (even signal, real data) */
  1514. void
  1515. cs_array_magnitude (a,n)
  1516.      REAL *a;
  1517.      long n;
  1518. {
  1519.   long i, n2, ni;
  1520.   n2 = n/2;            /* integer division truncates down */
  1521.   a[0]  = (REAL) fabs((double) a[0]); /*   imag=0 */
  1522.   if (2*n2 == n)        /* even length, n2 is only real */
  1523.     a[n2] = (REAL) fabs((double) a[n2]); /*  imag=0 */
  1524.   else
  1525.     /* odd length, make the loop include the n2 index */
  1526.     n2 = n2+1;
  1527.   for (i=1; i<n2; i++)
  1528.     {
  1529.       ni = n-i;
  1530.       a[i]   = (REAL)  sqrt( (double) a[i]*a[i] + (double) a[ni]*a[ni] );
  1531.       a[ni]  = a[i];        /* even signal */
  1532.     }
  1533. }
  1534.  
  1535. /* Rectangular and Polar
  1536.    A cs-array has even magnitude and odd angle (almost)
  1537.    hence a polar cs-array stores magnitude in the first half (real part)
  1538.    and angle in the second half (imag part)
  1539.    except for a[0] real-only and a[n2] (n even)
  1540.    The angle of a[0] is either 0 (pos. sign) or pi (neg. sign),
  1541.    but there is no place in an n-point cs-array to store this, so
  1542.    a[0] and a[n2] when n even are left unchanged  when going polar.
  1543.    as opposed to taking their absolute values, for magnitude. */
  1544.  
  1545. DEFINE_PRIMITIVE ("CS-ARRAY-TO-POLAR!", Prim_cs_array_to_polar, 1,1, 0)
  1546. {
  1547.   long n, i;
  1548.   REAL *a;
  1549.   void cs_array_to_polar();
  1550.   PRIMITIVE_HEADER (1);
  1551.   CHECK_ARG (1, ARRAY_P);
  1552.   a  = ARRAY_CONTENTS(ARG_REF(1));
  1553.   n = ARRAY_LENGTH(ARG_REF(1));
  1554.   cs_array_to_polar(a,n);
  1555.   PRIMITIVE_RETURN (UNSPECIFIC);
  1556. }
  1557.  
  1558. void
  1559. cs_array_to_polar (a,n)
  1560.      REAL *a;
  1561.      long n;
  1562. {
  1563.   long i, n2;
  1564.   double real, imag;        /* temporary variables */
  1565.   n2 = n/2;            /* integer division truncates down */
  1566.   /* a[0] stores both magnitude and angle
  1567.      (pos. sign angle=0 , neg. sign angle=pi) */
  1568.   if (2*n2 == n)        /* even length, n2 is only real */
  1569.     ;                /* a[n2] stores sign information like a[0] */
  1570.   else
  1571.     /* odd length, make the loop include the n2 index */
  1572.     n2 = n2+1;
  1573.   for (i=1; i<n2; i++)
  1574.     {
  1575.       real = (double) a[i];
  1576.       imag = (double) a[n-i];
  1577.       a[i]   = (REAL)  sqrt( real*real + imag*imag );
  1578.       if (a[i] == 0.0)
  1579.     a[n-i] = 0.0;
  1580.       else
  1581.     a[n-i] = (REAL) atan2( imag, real );
  1582.     }
  1583. }
  1584.  
  1585. DEFINE_PRIMITIVE ("CS-ARRAY-TO-RECTANGULAR!", Prim_cs_array_to_rectangular, 1,1, 0)
  1586. {
  1587.   long n,n2, i;
  1588.   double magn,angl;        /* temporary variables */
  1589.   REAL *a;
  1590.   PRIMITIVE_HEADER (1);
  1591.   CHECK_ARG (1, ARRAY_P);
  1592.   a  = ARRAY_CONTENTS(ARG_REF(1));
  1593.   n = ARRAY_LENGTH(ARG_REF(1));
  1594.   n2 = n/2;            /* integer division truncates down */
  1595.   ;                /* a[0] is okay */
  1596.   if (2*n2 == n)        /* even length, n2 is real only */
  1597.     ;                /* a[n2] is okay */
  1598.   else
  1599.     n2 = n2+1; /* odd length, make the loop include the n2 index */
  1600.   for (i=1; i<n2; i++)
  1601.   { magn = (double) a[i];
  1602.     angl = (double) a[n-i];
  1603.     a[i]   = (REAL)  magn * cos(angl);
  1604.     a[n-i] = (REAL)  magn * sin(angl); }
  1605.   PRIMITIVE_RETURN (UNSPECIFIC);
  1606. }
  1607.  
  1608. /* Convolution in the Time-Domain */
  1609. /* In the following macro
  1610.    To1 and To2 should be (Length1-1) and (Length2-1) respectively. */
  1611.  
  1612. #define C_Convolution_Point_Macro(X, Y, To1, To2, N, Result)        \
  1613. {                                    \
  1614.   long Min_of_N_To1 = (min ((N), (To1)));                \
  1615.   long mi, N_minus_mi;                            \
  1616.   REAL Sum = 0.0;                            \
  1617.   for (mi = (max (0, ((N) - (To2)))), N_minus_mi = ((N) - mi);        \
  1618.        (mi <= Min_of_N_To1);                        \
  1619.        mi += 1, N_minus_mi -= 1)                    \
  1620.     Sum += ((X [mi]) * (Y [N_minus_mi]));                \
  1621.   (Result) = Sum;                            \
  1622. }
  1623.  
  1624. DEFINE_PRIMITIVE ("CONVOLUTION-POINT", Prim_convolution_point, 3, 3, 0)
  1625. {
  1626.   long Length1, Length2, N;
  1627.   REAL *Array1, *Array2;
  1628.   REAL C_Result;
  1629.   PRIMITIVE_HEADER (3);
  1630.   CHECK_ARG (1, ARRAY_P);
  1631.   CHECK_ARG (2, ARRAY_P);
  1632.   Length1 = ARRAY_LENGTH (ARG_REF (1));
  1633.   Length2 = ARRAY_LENGTH (ARG_REF (2));
  1634.   N = (arg_nonnegative_integer (3));
  1635.   Array1 = ARRAY_CONTENTS (ARG_REF (1));
  1636.   Array2 = ARRAY_CONTENTS (ARG_REF (2));
  1637.   C_Convolution_Point_Macro(Array1, Array2, Length1-1, Length2-1, N, C_Result);
  1638.   PRIMITIVE_RETURN (double_to_flonum ((double) C_Result));
  1639. }
  1640.  
  1641. DEFINE_PRIMITIVE ("ARRAY-CONVOLUTION-IN-TIME!", Prim_array_convolution_in_time, 3, 3, 0)
  1642. {
  1643.   long n,m,l, n_1,m_1, i;
  1644.   REAL *a,*b,*c;
  1645.   PRIMITIVE_HEADER (3);
  1646.   CHECK_ARG (1, ARRAY_P);
  1647.   CHECK_ARG (2, ARRAY_P);
  1648.   CHECK_ARG (3, ARRAY_P);
  1649.   a = ARRAY_CONTENTS(ARG_REF(1));
  1650.   b = ARRAY_CONTENTS(ARG_REF(2));
  1651.   c = ARRAY_CONTENTS(ARG_REF(3));
  1652.   n = ARRAY_LENGTH(ARG_REF(1));
  1653.   m = ARRAY_LENGTH(ARG_REF(2));
  1654.   l = n+m-1;            /* resulting length */
  1655.   if (l != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1656.   n_1 = n-1; m_1 = m-1;
  1657.   for (i=0; i<l; i++)
  1658.   { C_Convolution_Point_Macro(a, b, n_1, m_1, i, c[i]); }
  1659.   PRIMITIVE_RETURN (UNSPECIFIC);
  1660. }
  1661.  
  1662. DEFINE_PRIMITIVE ("ARRAY-MULTIPLY-INTO-SECOND-ONE!", Prim_array_multiply_into_second_one, 2, 2, 0)
  1663. {
  1664.   long Length, i;
  1665.   REAL *To_Here;
  1666.   REAL *From_Here_1, *From_Here_2;
  1667.   PRIMITIVE_HEADER (2);
  1668.   CHECK_ARG (1, ARRAY_P);
  1669.   CHECK_ARG (2, ARRAY_P);
  1670.   Length = ARRAY_LENGTH (ARG_REF (1));
  1671.   if (Length != ARRAY_LENGTH (ARG_REF (2))) error_bad_range_arg (2);
  1672.   From_Here_1 = ARRAY_CONTENTS (ARG_REF (1));
  1673.   From_Here_2 = ARRAY_CONTENTS (ARG_REF (2));
  1674.   To_Here = From_Here_2;
  1675.   for (i=0; i < Length; i++)
  1676.     {
  1677.       *To_Here++ = (*From_Here_1) * (*From_Here_2);
  1678.       From_Here_1++ ;
  1679.       From_Here_2++ ;
  1680.     }
  1681.   PRIMITIVE_RETURN (UNSPECIFIC);
  1682. }
  1683.  
  1684. /* complex-array-operation-2!
  1685.    groups together procedures that use 2 complex-arrays
  1686.    and store result in either 1st or 2nd */
  1687.  
  1688. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-2!", Prim_complex_array_operation_2, 5,5, 0)
  1689. {
  1690.   long n, opcode;
  1691.   REAL *ax,*ay, *bx,*by;
  1692.   void complex_array_multiply_into_second_one();
  1693.   PRIMITIVE_HEADER (5);
  1694.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1695.   CHECK_ARG (2, ARRAY_P);    /* ax array -- n      real         */
  1696.   CHECK_ARG (3, ARRAY_P);    /* ay array -- n      imag         */
  1697.   CHECK_ARG (4, ARRAY_P);    /* bx array -- n      real         */
  1698.   CHECK_ARG (5, ARRAY_P);    /* by array -- n      imag         */
  1699.   n = ARRAY_LENGTH(ARG_REF(2));
  1700.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1701.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(4);
  1702.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(5);
  1703.   ax  = ARRAY_CONTENTS(ARG_REF(2)); /*  real */
  1704.   ay  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag */
  1705.   bx  = ARRAY_CONTENTS(ARG_REF(4)); /*  real */
  1706.   by  = ARRAY_CONTENTS(ARG_REF(5)); /*  imag */
  1707.   opcode = arg_nonnegative_integer(1);
  1708.   if (opcode==1)
  1709.     complex_array_multiply_into_second_one(ax,ay,bx,by, n);
  1710.   else if (opcode==2)
  1711.     error_bad_range_arg(1);    /* illegal opcode */
  1712.   else
  1713.     error_bad_range_arg(1);    /* illegal opcode */
  1714.   PRIMITIVE_RETURN (UNSPECIFIC);
  1715. }
  1716.  
  1717. void
  1718. complex_array_multiply_into_second_one (ax,ay,bx,by, n)
  1719.      REAL *ax,*ay,*bx,*by;
  1720.      long n;
  1721. {
  1722.   long i;
  1723.   REAL temp;
  1724.   for (i=0;i<n;i++)
  1725.     {
  1726.       temp   = ax[i]*bx[i]  -  ay[i]*by[i]; /*  real part */
  1727.       by[i]  = ax[i]*by[i]  +  ay[i]*bx[i]; /*  imag part */
  1728.       bx[i]  = temp;
  1729.     }
  1730. }
  1731.  
  1732. void
  1733. C_Array_Complex_Multiply_Into_First_One (a,b,c,d, length) /* used in fft.c */
  1734.      REAL *a,*b,*c,*d;
  1735.      long length;
  1736. {
  1737.   long i;
  1738.   REAL temp;
  1739.   for (i=0;i<length;i++)
  1740.     {
  1741.       temp = a[i]*c[i] - b[i]*d[i];
  1742.       b[i] = a[i]*d[i] + b[i]*c[i];
  1743.       a[i] = temp;
  1744.     }
  1745. }
  1746.  
  1747. DEFINE_PRIMITIVE ("ARRAY-DIVIDE-INTO-XXX!", Prim_array_divide_into_xxx, 4,4, 0)
  1748. {
  1749.   long n, i, one_or_two;
  1750.   REAL *x,*y,*z, inf;
  1751.   void array_divide_into_z();
  1752.   PRIMITIVE_HEADER (4);
  1753.   CHECK_ARG (1, ARRAY_P);
  1754.   CHECK_ARG (2, ARRAY_P);
  1755.   inf = (arg_real (3));
  1756.   /* where to store result of division */
  1757.   one_or_two = (arg_nonnegative_integer (4));
  1758.   x = ARRAY_CONTENTS(ARG_REF(1));
  1759.   y = ARRAY_CONTENTS(ARG_REF(2));
  1760.   n = ARRAY_LENGTH(ARG_REF(1));
  1761.   if (n!=(ARRAY_LENGTH(ARG_REF(2)))) error_bad_range_arg(2);
  1762.   if (one_or_two == 1)
  1763.     array_divide_into_z( x,y, x,  n, inf);
  1764.   else if (one_or_two == 2)
  1765.     array_divide_into_z( x,y, y,  n, inf);
  1766.   else
  1767.     error_bad_range_arg(4);
  1768.   PRIMITIVE_RETURN (UNSPECIFIC);
  1769. }
  1770.  
  1771. void
  1772. array_divide_into_z (x,y, z, n, inf) /* z can either x or y */
  1773.      REAL *x,*y,*z, inf;
  1774.      long n;
  1775. {
  1776.   long i;
  1777.   for (i=0; i<n; i++)
  1778.     {
  1779.       if (y[i] == 0.0)
  1780.     {
  1781.       if (x[i] == 0.0)
  1782.         z[i] = 1.0;
  1783.       else
  1784.         z[i] = inf * x[i];
  1785.     }
  1786.       else
  1787.     z[i] = x[i] / y[i];
  1788.     }
  1789. }
  1790.  
  1791. /* complex-array-operation-2b!
  1792.    groups together procedures that use 2 complex-arrays
  1793.    & 1 additional real number
  1794.    and store result in either 1st or 2nd (e.g. division) */
  1795.  
  1796. DEFINE_PRIMITIVE ("COMPLEX-ARRAY-OPERATION-2B!", Prim_complex_array_operation_2b, 6,6, 0)
  1797. { long n, opcode;
  1798.   REAL *ax,*ay, *bx,*by,  inf;
  1799.   void complex_array_divide_into_z();
  1800.   PRIMITIVE_HEADER (6);
  1801.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  1802.   CHECK_ARG (2, ARRAY_P);    /* ax array -- n      real         */
  1803.   CHECK_ARG (3, ARRAY_P);    /* ay array -- n      imag         */
  1804.   CHECK_ARG (4, ARRAY_P);    /* bx array -- n      real         */
  1805.   CHECK_ARG (5, ARRAY_P);    /* by array -- n      imag         */
  1806.   inf = (arg_real (6));        /* User-Provided Infinity */
  1807.   n = ARRAY_LENGTH(ARG_REF(2));
  1808.   if (n != ARRAY_LENGTH(ARG_REF(3))) error_bad_range_arg(3);
  1809.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(4);
  1810.   if (n != ARRAY_LENGTH(ARG_REF(4))) error_bad_range_arg(5);
  1811.   ax  = ARRAY_CONTENTS(ARG_REF(2)); /*  real */
  1812.   ay  = ARRAY_CONTENTS(ARG_REF(3)); /*  imag */
  1813.   bx  = ARRAY_CONTENTS(ARG_REF(4)); /*  real */
  1814.   by  = ARRAY_CONTENTS(ARG_REF(5)); /*  imag */
  1815.   opcode = arg_nonnegative_integer(1);
  1816.   if (opcode==1)
  1817.     complex_array_divide_into_z (ax,ay,bx,by, ax,ay,  n, inf);
  1818.   else if (opcode==2)
  1819.     complex_array_divide_into_z (ax,ay,bx,by, bx,by,  n, inf);
  1820.   else
  1821.     error_bad_range_arg(1);    /* illegal opcode */
  1822.   PRIMITIVE_RETURN (UNSPECIFIC);
  1823. }
  1824.  
  1825. void
  1826. complex_array_divide_into_z (xr,xi, yr,yi, zr,zi, n, inf)
  1827.      REAL *xr,*xi, *yr,*yi, *zr,*zi, inf;
  1828.      long n;
  1829. {
  1830.   long i;
  1831.   fast double temp, radius;
  1832.   for (i=0; i<n; i++)
  1833.     {
  1834.       radius = (double) (yr[i] * yr[i]) + (yi[i] * yi[i]); /* denominator */
  1835.       if (radius == 0.0)
  1836.     {
  1837.       if (xr[i] == 0.0)
  1838.         zr[i] = 1.0;
  1839.       else
  1840.         zr[i] = inf * xr[i];
  1841.       if (xi[i] == 0.0)
  1842.         zi[i] = 1.0;
  1843.       else
  1844.         zi[i] = inf * xi[i];
  1845.     }
  1846.       else
  1847.     {
  1848.       temp =  (double) (xr[i] * yr[i]  +  xi[i] * yi[i]);
  1849.       zi[i] = (REAL) (xi[i] * yr[i]  -  xr[i] * yi[i]) / radius;
  1850.       zr[i] = (REAL) temp                              / radius;
  1851.     }
  1852.     }
  1853. }
  1854.  
  1855. DEFINE_PRIMITIVE ("ARRAY-LINEAR-SUPERPOSITION-INTO-SECOND-ONE!", Prim_array_linear_superposition_into_second_one, 4, 4, 0)
  1856. {
  1857.   long n, i;
  1858.   REAL *To_Here, Coeff1, Coeff2;
  1859.   REAL *From_Here_1, *From_Here_2;
  1860.   PRIMITIVE_HEADER (4);
  1861.   Coeff1 = (arg_real (1));
  1862.   CHECK_ARG (2, ARRAY_P);
  1863.   Coeff2 = (arg_real (3));
  1864.   CHECK_ARG (4, ARRAY_P);
  1865.   n = (ARRAY_LENGTH (ARG_REF (2)));
  1866.   if (n != (ARRAY_LENGTH (ARG_REF (4))))
  1867.     error_bad_range_arg (4);
  1868.   From_Here_1 = (ARRAY_CONTENTS (ARG_REF (2)));
  1869.   From_Here_2 = (ARRAY_CONTENTS (ARG_REF (4)));
  1870.   To_Here = From_Here_2;
  1871.   for (i=0; i < n; i++)
  1872.     {
  1873.       *To_Here++ = (Coeff1 * (*From_Here_1)) + (Coeff2 * (*From_Here_2));
  1874.       From_Here_1++ ;
  1875.       From_Here_2++ ;
  1876.     }
  1877.   PRIMITIVE_RETURN (UNSPECIFIC);
  1878. }
  1879.  
  1880. /*  m_pi = 3.14159265358979323846264338327950288419716939937510; */
  1881.  
  1882. DEFINE_PRIMITIVE ("SAMPLE-PERIODIC-FUNCTION", Prim_sample_periodic_function, 4, 4, 0)
  1883. {
  1884.   long N, i, Function_Number;
  1885.   double Signal_Frequency, Sampling_Frequency, DT, DTi;
  1886.   double twopi = 6.28318530717958;
  1887.   SCHEME_OBJECT Result, Pfunction_number, Psignal_frequency;
  1888.   SCHEME_OBJECT Pfunction_Number;
  1889.   REAL *To_Here;
  1890.   double unit_square_wave(), unit_triangle_wave();
  1891.   PRIMITIVE_HEADER (4);
  1892.   Function_Number = (arg_index_integer (1, 11));
  1893.   Signal_Frequency = (arg_real_number (2));
  1894.   if (Signal_Frequency == 0)
  1895.     error_bad_range_arg (2);
  1896.   Sampling_Frequency = (arg_real_number (3));
  1897.   if (Sampling_Frequency == 0)
  1898.     error_bad_range_arg (3);
  1899.   N = (arg_nonnegative_integer (4));
  1900.   Result = (allocate_array (N));
  1901.   To_Here = ARRAY_CONTENTS(Result);
  1902.   DT = (double) (twopi * Signal_Frequency * (1 / Sampling_Frequency));
  1903.   if (Function_Number == 0)
  1904.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1905.       *To_Here++ = (REAL) cos(DTi);
  1906.   else if (Function_Number == 1)
  1907.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1908.       *To_Here++ = (REAL) sin(DTi);
  1909.   else if (Function_Number == 2)
  1910.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1911.       *To_Here++ = (REAL) unit_square_wave(DTi);
  1912.   else if (Function_Number == 3)
  1913.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  1914.       *To_Here++ = (REAL) unit_triangle_wave(DTi);
  1915.   else
  1916.     error_bad_range_arg (1);
  1917.   PRIMITIVE_RETURN (Result);
  1918. }
  1919. ;
  1920. double
  1921. hamming (t, length)
  1922.      double t, length;
  1923. {
  1924.   double twopi = 6.28318530717958;
  1925.   double pi = twopi/2.;
  1926.   double t_bar = cos(twopi * (t / length));
  1927.   if ((t<length) && (t>0.0)) return(.08 + .46 * (1 - t_bar));
  1928.   else return (0);
  1929. }
  1930.  
  1931. double
  1932. unit_square_wave (t)
  1933.      double t;
  1934. {
  1935.   double twopi = 6.28318530717958;
  1936.   double fmod(), fabs();
  1937.   double pi = twopi/2.;
  1938.   double t_bar = ((REAL) fabs(fmod( ((double) t), twopi)));
  1939.   if (t_bar < pi) return(1);
  1940.   else return(-1);
  1941. }
  1942.  
  1943. double
  1944. unit_triangle_wave (t)
  1945.      double t;
  1946. {
  1947.   double twopi = 6.28318530717958;
  1948.   double pi = twopi/2.;
  1949.   double pi_half = pi/2.;
  1950.   double three_pi_half = pi+pi_half;
  1951.   double t_bar = ((double) fabs(fmod( ((double) t), twopi)));
  1952.   if (t_bar<pi_half)
  1953.     return (-(t_bar/pi));
  1954.   else if (t_bar<pi)
  1955.     return (t_bar/pi);
  1956.   else if (t_bar<three_pi_half)
  1957.     return ((twopi-t_bar)/pi);
  1958.   else
  1959.     return (-((twopi-t_bar)/pi));
  1960. }
  1961.  
  1962. DEFINE_PRIMITIVE ("ARRAY-HANNING!", Prim_array_hanning, 2,2, 0)
  1963. {
  1964.   long n, hanning_power;
  1965.   REAL *a;
  1966.   void C_Array_Make_Hanning();
  1967.   PRIMITIVE_HEADER (2);
  1968.   CHECK_ARG (1, ARRAY_P);    /* input array -- n */
  1969.   CHECK_ARG (2, FIXNUM_P);    /* hanning power */
  1970.   a  = ARRAY_CONTENTS(ARG_REF(1));
  1971.   n = ARRAY_LENGTH(ARG_REF(1));
  1972.   hanning_power = arg_nonnegative_integer(2);
  1973.   C_Array_Make_Hanning (a, n, hanning_power);
  1974.   PRIMITIVE_RETURN (UNSPECIFIC);
  1975. }
  1976.  
  1977. void
  1978. C_Array_Make_Hanning (f1, length, power)
  1979.      REAL f1[];
  1980.      long length, power;
  1981. {
  1982.   double window_length;
  1983.   long i;
  1984.   double integer_power(), hanning();
  1985.   window_length = ((double) length);
  1986.   for (i=0;i<length;i++)
  1987.     {
  1988.       f1[i] = ((REAL) hanning(((double) i), window_length));
  1989.       f1[i] = (REAL) integer_power(((double) f1[i]), power);
  1990.     }
  1991. }
  1992.  
  1993. double
  1994. hanning (t, length)
  1995.      double t, length;
  1996. {
  1997.   double twopi = 6.283185307179586476925287;
  1998.   double t_bar;
  1999.   t_bar = cos(twopi * (t / length));
  2000.   if ((t<length) && (t>0.0))
  2001.     return(.5 * (1 - t_bar));
  2002.   else
  2003.     return (0.0);
  2004. }
  2005.  
  2006. double
  2007. integer_power (a, n)
  2008.      double a;
  2009.      long n;
  2010. {
  2011.   double b;
  2012.   double integer_power();
  2013.  
  2014.   if (n<0) exit(-1);
  2015.   else if (n==0) return(1.0);
  2016.   else if (n==1) return(a);
  2017.   else if ((n%2) == 0)
  2018.     {
  2019.       b = integer_power(a, n/2);
  2020.       return(b*b);
  2021.     }
  2022.   else
  2023.     return(a * integer_power(a, (n-1)));
  2024. }
  2025.  
  2026. /* array-operation-1!
  2027.    groups together procedures that use 1 array
  2028.    and store the result in place (e.g. random) */
  2029.  
  2030. DEFINE_PRIMITIVE ("ARRAY-OPERATION-1!", Prim_array_operation_1, 2,2, 0)
  2031. {
  2032.   long n, opcode;
  2033.   REAL *a;
  2034.   void array_random();
  2035.   PRIMITIVE_HEADER (2);
  2036.   CHECK_ARG (1, FIXNUM_P);    /* operation opcode */
  2037.   CHECK_ARG (2, ARRAY_P);    /* input array -- n */
  2038.   n = ARRAY_LENGTH(ARG_REF(2));
  2039.   a  = ARRAY_CONTENTS(ARG_REF(2));
  2040.   opcode = arg_nonnegative_integer(1);
  2041.   if (opcode==1)
  2042.     array_random(a,n);
  2043.   else if (opcode==2)
  2044.     error_bad_range_arg(1);    /* illegal opcode */
  2045.   else
  2046.     error_bad_range_arg(1);    /* illegal opcode */
  2047.   PRIMITIVE_RETURN (UNSPECIFIC);
  2048. }
  2049.  
  2050. void
  2051. array_random (a,n)
  2052.      REAL *a;
  2053.      long n;
  2054. {
  2055.   long i;
  2056.   /* HPUX 3: Rand uses a multiplicative congruential random-number generator
  2057.      with period 2^32 that returns successive pseudo-random numbers in the
  2058.      range from 0 to 2^15-1 */
  2059.   for (i=0;i<n;i++)
  2060.     a[i] = ((REAL) rand()) * (3.0517578125e-5);
  2061.   /* 3.051xxx = 2^(-15) makes the range from 0 to 1 */
  2062. }
  2063.  
  2064. /* The following should go away.
  2065.    superceded by ARRAY-CONS-INTEGERS, ARRAY-UNARY-FUNCTION and array-random */
  2066. DEFINE_PRIMITIVE ("SAMPLE-APERIODIC-FUNCTION", Prim_sample_aperiodic_function, 3, 3, 0)
  2067. {
  2068.   long N, i, Function_Number;
  2069.   double Sampling_Frequency, DT, DTi;
  2070.   double twopi = 6.28318530717958;
  2071.   SCHEME_OBJECT Result;
  2072.   REAL *To_Here, twopi_dt;
  2073.   PRIMITIVE_HEADER (3);
  2074.   Function_Number = (arg_index_integer (1, 7));
  2075.   Sampling_Frequency = (arg_real_number (2));
  2076.   if (Sampling_Frequency == 0)
  2077.     error_bad_range_arg (2);
  2078.   N = (arg_nonnegative_integer (3));
  2079.   Result = (allocate_array (N));
  2080.   To_Here = ARRAY_CONTENTS(Result);
  2081.   DT = (twopi * (1 / Sampling_Frequency));
  2082.   if      (Function_Number == 0)
  2083.     /* HPUX 3: Rand uses a multiplicative congruential random-number generator
  2084.        with period 2^32 that returns successive pseudo-random numbers in the
  2085.        range from 0 to 2^15-1 */
  2086.     for (i=0; i<N; i++)
  2087.       /* 2^(-15) makes range from 0 to 1 */
  2088.       *To_Here++ = 3.0517578125e-5 * ((REAL) rand());
  2089.   else if (Function_Number == 1)
  2090.   { double length=DT*N;
  2091.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2092.       *To_Here++ = (REAL) hanning(DTi, length);
  2093.   }
  2094.   else if (Function_Number == 2)
  2095.   { double length=DT*N;
  2096.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2097.       *To_Here++ = (REAL) hamming(DTi, length);
  2098.   }
  2099.   else if (Function_Number == 3)
  2100.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2101.       *To_Here++ = (REAL) sqrt(DTi);
  2102.   else if (Function_Number == 4)
  2103.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2104.       *To_Here++ = (REAL) log(DTi);
  2105.   else if (Function_Number == 5)
  2106.     for (i=0, DTi=0.0; i < N; i++, DTi += DT)
  2107.       *To_Here++ = (REAL) exp(DTi);
  2108.   else
  2109.     error_bad_range_arg (1);
  2110.   PRIMITIVE_RETURN (Result);
  2111. }
  2112.  
  2113. DEFINE_PRIMITIVE ("ARRAY-PERIODIC-DOWNSAMPLE", Prim_array_periodic_downsample, 2, 2, 0)
  2114. {
  2115.   long Length, Pseudo_Length, Sampling_Ratio;
  2116.   REAL *Array, *To_Here;
  2117.   SCHEME_OBJECT Result;
  2118.   long i, array_index;
  2119.   PRIMITIVE_HEADER (2);
  2120.   CHECK_ARG (1, ARRAY_P);
  2121.   Length = ARRAY_LENGTH(ARG_REF (1));
  2122.   Sampling_Ratio = ((arg_integer (2)) % Length);
  2123.   if (Sampling_Ratio < 1)
  2124.     error_bad_range_arg (2);
  2125.   Array = ARRAY_CONTENTS(ARG_REF (1));
  2126.   Result = (allocate_array (Length));
  2127.   To_Here = ARRAY_CONTENTS(Result);
  2128.   Pseudo_Length = Length * Sampling_Ratio;
  2129.   /* new Array has the same Length by assuming periodicity */
  2130.   for (i=0; i<Pseudo_Length; i += Sampling_Ratio)
  2131.   { array_index = i % Length;
  2132.     *To_Here++ = Array[array_index]; }
  2133.   PRIMITIVE_RETURN (Result);
  2134. }
  2135.  
  2136. /* Shift is not done in place (no side-effects). */
  2137. DEFINE_PRIMITIVE ("ARRAY-PERIODIC-SHIFT", Prim_array_periodic_shift, 2, 2, 0)
  2138. {
  2139.   long Length, Shift;
  2140.   REAL *Array, *To_Here;
  2141.   SCHEME_OBJECT Result;
  2142.   long i, array_index;
  2143.   PRIMITIVE_HEADER (2);
  2144.   CHECK_ARG (1, ARRAY_P);
  2145.   Length = ARRAY_LENGTH(ARG_REF (1));
  2146.   /* periodic waveform, same sign as dividend */
  2147.   Shift = ((arg_integer (2)) % Length);
  2148.   Array = ARRAY_CONTENTS(ARG_REF (1));
  2149.   Result = (allocate_array (Length));
  2150.   To_Here = ARRAY_CONTENTS(Result);
  2151.   /* new Array has the same Length by assuming periodicity */
  2152.   for (i=0; i<Length; i++) {
  2153.     array_index = (i+Shift) % Length;
  2154.     if (array_index<0) array_index = Length + array_index; /* wrap around */
  2155.     *To_Here++ = Array[array_index]; }
  2156.   PRIMITIVE_RETURN (Result);
  2157. }
  2158.  
  2159. /* This is done here because array-map is very slow */
  2160. DEFINE_PRIMITIVE ("ARRAY-APERIODIC-DOWNSAMPLE", Prim_array_aperiodic_downsample, 2, 2, 0)
  2161. {
  2162.   long Length, New_Length, Sampling_Ratio;
  2163.   REAL *Array, *To_Here;
  2164.   SCHEME_OBJECT Result;
  2165.   long i, array_index;
  2166.   PRIMITIVE_HEADER (2);
  2167.   CHECK_ARG (1, ARRAY_P);
  2168.   Array = ARRAY_CONTENTS(ARG_REF (1));
  2169.   Length = ARRAY_LENGTH(ARG_REF (1));
  2170.   Sampling_Ratio = (arg_integer_in_range (2, 1, (Length + 1)));
  2171.   if (Length < 1) error_bad_range_arg (1);
  2172.   /* 1 for first one and then the rest --- integer division chops */
  2173.   New_Length = 1 + ((Length-1)/Sampling_Ratio);
  2174.   Result = (allocate_array (New_Length));
  2175.   To_Here = ARRAY_CONTENTS(Result);
  2176.   for (i=0; i<Length; i += Sampling_Ratio)
  2177.     *To_Here++ = Array[i];
  2178.   PRIMITIVE_RETURN (Result);
  2179. }
  2180.  
  2181. /* one more hack for speed */
  2182.  
  2183. /* (SOLVE-SYSTEM A B N)
  2184.     Solves the system of equations Ax = b.  A and B are
  2185.     arrays and b is the order of the system.  Returns x.
  2186.     From the Fortran procedure in Strang. */
  2187.  
  2188. DEFINE_PRIMITIVE ("SOLVE-SYSTEM", Prim_gaussian_elimination, 2, 2, 0)
  2189. {
  2190.   REAL *A, *B, *X;
  2191.   long Length;
  2192.   SCHEME_OBJECT Result;
  2193.   PRIMITIVE_HEADER (2);
  2194.   CHECK_ARG (1, ARRAY_P);
  2195.   CHECK_ARG (2, ARRAY_P);
  2196.   Length  = ARRAY_LENGTH(ARG_REF (2));
  2197.   if ((Length*Length) != ARRAY_LENGTH(ARG_REF (1))) error_bad_range_arg (2);
  2198.   A = ARRAY_CONTENTS(ARG_REF (1));
  2199.   B = ARRAY_CONTENTS(ARG_REF (2));
  2200.   Result = (allocate_array (Length));
  2201.   X = ARRAY_CONTENTS(Result);
  2202.   C_Array_Copy(B, X, Length);
  2203.   C_Gaussian_Elimination(A, X, Length);
  2204.   PRIMITIVE_RETURN (Result);
  2205. }
  2206.  
  2207. /* C routine side-effects b. */
  2208. C_Gaussian_Elimination (a, b, n)
  2209.      REAL *a, *b;
  2210.      long n;
  2211. {
  2212.   long *pvt;
  2213.   REAL p, t;
  2214.   long i, j, k, m;
  2215.   Primitive_GC_If_Needed (n);
  2216.   pvt = ((long *) Free);
  2217.   *(pvt+n-1) = 1;
  2218.   if (n != 1) {
  2219.     for (k=1; k<n; k++) {
  2220.       m = k;
  2221.       for (i=k+1; i<=n; i++)
  2222.     if (fabs(*(a+i+(k-1)*n-1)) > fabs(*(a+m+(k-1)*n-1)))
  2223.       m = i;
  2224.       *(pvt+k-1) = m;
  2225.       if (m != k)
  2226.     *(pvt+n-1) = - *(pvt+n-1);
  2227.       p = *(a+m+(k-1)*n-1);
  2228.       *(a+m+(k-1)*n-1) = *(a+k+(k-1)*n-1);
  2229.       *(a+k+(k-1)*n-1) = p;
  2230.       if (p != 0.0) {
  2231.     for (i=k+1; i<=n; i++)
  2232.       *(a+i+(k-1)*n-1) = - *(a+i+(k-1)*n-1) / p;
  2233.     for (j=k+1; j<=n; j++) {
  2234.       t = *(a+m+(j-1)*n-1);
  2235.       *(a+m+(j-1)*n-1) = *(a+k+(j-1)*n-1);
  2236.       *(a+k+(j-1)*n-1) = t;
  2237.       if (t != 0.0)
  2238.         for (i=k+1; i<=n; i++)
  2239.           *(a+i+(j-1)*n-1) = *(a+i+(j-1)*n-1) + *(a+i+(k-1)*n-1) * t;
  2240.     }
  2241.       }
  2242.     }
  2243.     for (k=1; k<n; k++) {
  2244.       m = *(pvt+k-1);
  2245.       t = *(b+m-1);
  2246.       *(b+m-1) = *(b+k-1);
  2247.       *(b+k-1) = t;
  2248.       for (i=k+1; i<=n; i++)
  2249.     *(b+i-1) = *(b+i-1) + *(a+i+(k-1)*n-1) * t;
  2250.     }
  2251.     for (j=1; j<n; j++) {
  2252.       k = n - j + 1;
  2253.       *(b+k-1) = *(b+k-1) / *(a+k+(k-1)*n-1);
  2254.       t = - *(b+k-1);
  2255.       for (i=1; i <= n-j; i++)
  2256.     *(b+i-1) = *(b+i-1) + *(a+i+(k-1)*n-1) * t;
  2257.     }
  2258.   }
  2259.   *b = *b / *a;
  2260.   return;
  2261. }
  2262.